package openbang.account.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import java.util.logging.Logger;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.JDOUserException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.appengine.api.users.UserServiceFailureException;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import openbang.account.service.entity.Group;
import openbang.account.service.entity.MediaObject;
import openbang.account.service.entity.VerifyRecord;
import openbang.account.service.entity.UserAccount;
import openbang.account.service.intf.AccountService;
import openbang.account.service.util.CacheHelper;
import openbang.account.service.util.EmailHelper;
import openbang.account.service.util.PMF;
import openbang.account.service.util.SessionHelper;
import openbang.account.service.vo.AccountServiceEnum;
import openbang.account.service.vo.BusinessEnum;
import openbang.account.service.vo.VerifyStatusEnum;
import openbang.account.service.vo.GradeEnum;
import openbang.account.service.vo.PwdVerifyEnum;
import openbang.account.service.vo.UserLoginInfo;
import openbang.common.vo.SelectModel;

/**
 * 帐户后台管理服务
 * @author aibozeng
 *
 */

@SuppressWarnings("serial")
public class AccountServiceImpl  extends RemoteServiceServlet implements AccountService {
	private static final Logger log = Logger.getLogger(AccountServiceImpl.class.getName());
	
	public List<UserAccount> getAll() {
		log.warning("come in getAll User");
		SessionHelper.updUserLoginInfo(getThreadLocalRequest());
		PersistenceManager pm = PMF.get().getPersistenceManager();
		List<UserAccount> list = new ArrayList<UserAccount>();
		
		Collection<UserAccount> collection = (List<UserAccount>) pm.newQuery(UserAccount.class).execute();
		for(UserAccount u : collection){
			u=pm.detachCopy(u);
			list.add(u);
		}
		pm.close();
/*		list.add(new UserAccount(new Long(10),"aibozeng@gmail.com","zengyubo","阿博"));
		list.add(new UserAccount(new Long(11),"wangshubing@gmail.com","wangshubing","阿兵"));
		list.add(new UserAccount(new Long(12),"wanghaitao@gmail.com","wanghaitao","阿涛"));
		list.add(new UserAccount(new Long(13),"wangxuelian@gmail.com","wangxuelian","阿莲"));
*/		return list;
	}

	public List<SelectModel> getAllEmail() {
		log.warning("come in getAllEmail");
		SessionHelper.updUserLoginInfo(getThreadLocalRequest());
		PersistenceManager pm = PMF.get().getPersistenceManager();
		List<SelectModel> list = new ArrayList<SelectModel>();
		
		Collection<UserAccount> collection = (List<UserAccount>) pm.newQuery(UserAccount.class).execute();
		for(UserAccount u : collection){
			list.add(new SelectModel(u.getEmail(),u.getEmail(),u.getNiceName()));
		}
		pm.close();
		return list;
	}
	
	public Integer checkForLogin(String email, String pwd) {
		log.warning("come in checkForLogin email="+email+",pwd="+pwd);
		Integer retCode = 0;
		PersistenceManager pm = PMF.get().getPersistenceManager();
		UserAccount user = findByEmail(email,pm);
		if(user==null){
			retCode = AccountServiceEnum.ERR_EMAIL.getCode(); 
		}
		else{
			if(user.getPwd().equals(pwd)){
				retCode = AccountServiceEnum.OK.getCode(); 
				UserLoginInfo userInfo = new UserLoginInfo();
	            userAccount2UserLoginInfo(user,userInfo);
	            //放入Session中
	            SessionHelper.setUserLoginInfo(getThreadLocalRequest(), userInfo);				
			}
			else{
				retCode = AccountServiceEnum.ERR_PWD.getCode(); 
			}
		}
		if(!pm.isClosed()) pm.close();
		log.warning("retCode="+retCode);
		
		return retCode;				
	}

	@Override
	public Integer registerAccount(UserAccount account) {
		log.warning("come in registerAccount email="+account.getEmail());
		SessionHelper.updUserLoginInfo(getThreadLocalRequest());
		PersistenceManager pm = PMF.get().getPersistenceManager();
		if(findByEmail(account.getEmail(),pm)!=null){
			pm.close();
			return AccountServiceEnum.EXIST_EMAIL.getCode();
		}
		pm.makePersistent(account);
				
	    //产生随机验证码
		UUID uuid = UUID.randomUUID();
		String verifyCode = uuid.toString();
		//存入校验记录
		VerifyRecord fpr = new VerifyRecord();
		fpr.setEmail(account.getEmail());
		fpr.setVerifyCode(verifyCode);
		fpr.setBusiType(BusinessEnum.VERIFY_EMAIL.getCode());
		pm.makePersistent(fpr);	
		pm.close();
		
		//发出邮件 --验证邮箱
		StringBuffer body = new StringBuffer("亲爱的");
		body.append(account.getNiceName());
		body.append(":\n");
		body.append("   您于 ");
		//TODO Locale.SIMPLIFIED_CHINESE 应该来源于 session 中存放的用户使用的区域
		body.append( (new SimpleDateFormat("yyyy-MM-dd HH:mm",Locale.SIMPLIFIED_CHINESE)).format(fpr.getApplyTime()));
		body.append( " 在开源邦注册了新用户. 登录帐户为：");
		body.append( account.getEmail());
		body.append( " \n 请您及时把以下链接复制到浏览器地址栏,验证您的邮箱.今后可以通过邮箱找回您的密码:\n\n");
		String setupUrl = "";
	    setupUrl =  SessionHelper.getAppUrl(getThreadLocalRequest())+"/verifyEmail.do?email="+account.getEmail()+"&id="+verifyCode;
	    log.warning("verify url="+setupUrl);
		body.append(setupUrl);
		body.append("\n\n");
		body.append("    如果您没有注册过用户,可以忽略处理该邮件,可能是由于他人使用了您的信息，由此给您带来的不便敬请谅解.如果有空,请回复邮件告知我们是否有人恶意操作.\n");
		body.append("    祝您愉快\n");
		body.append("    开源邦 系统管理员\n");
 	    String REGISTER_subject = "欢迎您在开源邦(openbang.net)注册，请及时激活您的帐户";
		EmailHelper.send(account.getEmail(),REGISTER_subject,body.toString());		
		
		if(!pm.isClosed()) pm.close();
		log.warning("registerAccount over.");
		//TODO 给新用户发一个系统短信
		return AccountServiceEnum.OK.getCode();
	}

	public UserAccount findByEmail(String emailStr,PersistenceManager pm){
		Query q = pm.newQuery(UserAccount.class, "email == email_address");
		q.declareParameters("java.lang.String email_address");
		Collection<UserAccount> users = null;
		try{
	       users = (Collection<UserAccount>)q.execute(emailStr);
			if(users!=null && users.size()>0){
				//pm.close();
				UserAccount user = users.iterator().next();
			    //pm.detachCopy(user);
				return user;
			}
			else{
				//pm.close();
				return null;
			}
		}catch(JDOUserException jdou){
			log.warning(jdou.getMessage());
			log.warning("Do you have eclipse set to automatically run the datanucleus enhancer? What if you try cleaning the project with project->clean and then build the project from scratch?");
		}
		//
		return null;
	}

    
    /**
     * 获取已经登录的用户信息
     * 已经登录：
     * 1、在google帐户已经登录 , userService.getCurrentUser()
     * 2、在本站已经登录                       
     * @return
     */
    public UserLoginInfo getLoginUserInfo(String url){
    	log.warning("come in getLoginUserInfo()");
    	//1.优先判断 是否 session 中有值
    	UserLoginInfo userInfo = SessionHelper.getUserLoginInfo(getThreadLocalRequest());
    	if(userInfo.isLogined()){
    		return userInfo;
    	}
    	//2.是否在 Google 登录
        UserService userService = null;
        User googleUser = null;
        try{
        	userService = UserServiceFactory.getUserService();
	        if(userService.isUserLoggedIn()){
	        	googleUser = userService.getCurrentUser();
	        } 
        }catch(UserServiceFailureException userfe){
        	log.warning("catch UserServiceFailureException");
        	googleUser = null;
        }
        if (googleUser != null) {
        	//google中已经登录
            PersistenceManager pm = PMF.get().getPersistenceManager();
            UserAccount hasUserAccount = findByEmail(googleUser.getEmail(),pm);
            if(hasUserAccount==null){
            	//没有在本站注册，则自动注册
            	hasUserAccount = new UserAccount();
            	hasUserAccount.setEmail(googleUser.getEmail());
            	hasUserAccount.setNiceName(googleUser.getNickname());
            	hasUserAccount.setRemark("auto register from Google Account by LoggedIn.");
            	hasUserAccount.setUserName(googleUser.getNickname());
            	hasUserAccount.setVerifType(PwdVerifyEnum.GOOGLE.getCode());
            	pm.makePersistent(hasUserAccount);
            	if(!pm.isClosed()) pm.close();
            	//2010-04-09 给系统管理员发邮件通知
        		//发出邮件 --只是通知
        		StringBuffer body = new StringBuffer("亲爱的");
        		body.append(hasUserAccount.getNiceName());
        		body.append(":\n");
        		body.append("   您于 ");
        		//TODO Locale.SIMPLIFIED_CHINESE 应该来源于 session 中存放的用户使用的区域
        		body.append( (new SimpleDateFormat("yyyy-MM-dd HH:mm",Locale.SIMPLIFIED_CHINESE)).format(new Date()));
        		body.append( " 首次以Google统一登录的方式访问了开源邦,系统自动记录了你的邮箱信息,但没有记录您的密码. 登录帐户为：");
        		body.append( hasUserAccount.getEmail());
        		body.append( " \n 欢迎您继续访问开源邦!\n\n");
        		body.append("    祝您愉快\n");
        		body.append("    开源邦 系统管理员\n");
         	    String REGISTER_subject = "欢迎您首次访问开源邦(openbang.net)";
        		EmailHelper.send(hasUserAccount.getEmail(),REGISTER_subject,body.toString());            	
            }
    		if(!pm.isClosed()) pm.close();
            //但是，如果该邮箱已经在本站注册了帐户呢？是覆盖，还是？ -- 不管先
            userAccount2UserLoginInfo(hasUserAccount,userInfo);
            //放入Session中
            SessionHelper.setUserLoginInfo(getThreadLocalRequest(), userInfo);
        }
        else{
        	//增加 登录后页面参数
        	if(url!=null){
        		if(userService!=null){
        		   userInfo.setLoginUrl(userService.createLoginURL(url));
        		}
        		log.warning("LoginUrl="+userInfo.getLoginUrl());
        	}
        }
	    //log.warning(getThreadLocalRequest().getRequestURL().toString()); http://localhost:8888/accountService
	    //log.warning(getThreadLocalRequest().getRequestURI());  /accountService
	    //log.warning(getThreadLocalRequest().getContextPath()); war包 路径
        return userInfo;
    }
    
    private void userAccount2UserLoginInfo(UserAccount userAccount,UserLoginInfo userInfo){
        userInfo.setEmail(userAccount.getEmail());
        userInfo.setGrade(userAccount.getGrade());
        userInfo.setId(userAccount.getId());
        userInfo.setLogined(true);
        userInfo.setLoginUrl(SessionHelper.getLoginUrl(getThreadLocalRequest()));
        userInfo.setLogoutUrl(SessionHelper.getLogoutUrl(getThreadLocalRequest()));
        userInfo.setNiceName(userAccount.getNiceName());
        userInfo.setVerifyType(userAccount.getVerifyType());
        //加一些容错处理
        if(userInfo.getGrade()==null){
        	userInfo.setGrade(GradeEnum.NORMAL.getCode());
        }
        if(userInfo.getVerifyType()==null){
        	userInfo.setVerifyType(PwdVerifyEnum.OPENBANG.getCode());
        }
    }
    
	@Override
	public Integer findEmail(String email) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		if(findByEmail(email,pm)==null){
			pm.close();
			return AccountServiceEnum.ERR_EMAIL.getCode();//没有找到
		}
		pm.close();
		return AccountServiceEnum.OK.getCode();//找到
	}

	@Override
	public Integer findEmail4FindPwd(String email) {
		PersistenceManager pm = PMF.get().getPersistenceManager();
		UserAccount user = findByEmail(email,pm);
		pm.close();
		if(user==null){
			return AccountServiceEnum.ERR_EMAIL.getCode();//没有找到
		}
		if(user.getVerifyType()==PwdVerifyEnum.OPENBANG.getCode()){
		   return AccountServiceEnum.OK.getCode();//找到
		}
		else{
		   //不能找回
		   return AccountServiceEnum.ERR_FINDPWD.getCode();
		}
	}
	
	@Override
	public Integer applyFindPwd(String email) {
		log.warning("come in applyFindPwd email="+email);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		UserAccount user = findByEmail(email,pm);
		if(user==null){
			pm.close();
			return AccountServiceEnum.ERR_EMAIL.getCode();//没有找到
		}
		if(user.getVerifyType()!=PwdVerifyEnum.OPENBANG.getCode()){
		   //不能找回
		   pm.close();
		   return AccountServiceEnum.ERR_FINDPWD.getCode();
		}
		if(user.getEmailVerifyStatus()==VerifyStatusEnum.PENDING.getCode()){
			   //不能找回 ，因为没有邮箱验证
			   pm.close();
			   return AccountServiceEnum.ERR_NO_VERIFY_EMAIL.getCode();
		}

		
	    //产生随机验证码
		UUID uuid = UUID.randomUUID();
		String verifyCode = uuid.toString();
		//存入申请记录
		VerifyRecord fpr = new VerifyRecord();
		fpr.setEmail(email);
		fpr.setVerifyCode(verifyCode);
		fpr.setBusiType(BusinessEnum.FIND_PWD.getCode());
		pm.makePersistent(fpr);		
		if(!pm.isClosed()) pm.close();

		//发出邮件
		StringBuffer  findPwd_body = new StringBuffer("亲爱的");
		findPwd_body.append(user.getNiceName());
		findPwd_body.append(":\n");
		findPwd_body.append("   您于 ");
		findPwd_body.append( (new SimpleDateFormat("yyyy-MM-dd HH:mm",Locale.SIMPLIFIED_CHINESE)).format(fpr.getApplyTime()));
		findPwd_body.append( " 在开源邦申请密码找回. \n");
		findPwd_body.append( " 请您及时把以下链接复制到浏览器地址栏，可以进行设置新密码.\n\n");
		String setupUrl = "";
		   setupUrl = SessionHelper.getAppUrl(getThreadLocalRequest())+"/setupPwd.do?email="+user.getEmail()+"&id="+verifyCode;
		log.warning("find pwd url="+setupUrl);
		findPwd_body.append(setupUrl);
		findPwd_body.append("\n\n");
		findPwd_body.append("    如果您没有做过申请,可以忽略处理该邮件,以前的密码会一直有效.如果有空,请回复邮件告知我们是否有人恶意操作.\n");
		findPwd_body.append("    祝您愉快\n");
		findPwd_body.append("    开源邦 系统管理员\n");
		 String FindPwd_subject = "您在开源邦(openbang.net)申请找回密码，请及时处理";
		EmailHelper.send(email,FindPwd_subject,findPwd_body.toString());
		if(!pm.isClosed()) pm.close();
		log.warning("applyFindPwd ok. applyId="+fpr.getId());
		return AccountServiceEnum.OK.getCode();//申请成功
	}

	@Override
	public Integer setupNewPwd(Long applyId, String newPwd) {
		log.warning("come in setupNewPwd applyId="+applyId);
		SessionHelper.updUserLoginInfo(getThreadLocalRequest());
		PersistenceManager pm = PMF.get().getPersistenceManager();
		VerifyRecord findPwdRecord = null;
		try{
		   findPwdRecord = pm.getObjectById(VerifyRecord.class, applyId);
		}catch(JDOObjectNotFoundException jdoe){
			if(!pm.isClosed()) pm.close();
			return AccountServiceEnum.ERR_FINDPWD_APPLY.getCode();
		}
		
		if(findPwdRecord==null){
			pm.close();
			return AccountServiceEnum.ERR_FINDPWD_APPLY.getCode();//申请单找不到
		}
		UserAccount userAccount = findByEmail(findPwdRecord.getEmail(),pm);
		userAccount.setPwd(newPwd);
		userAccount.setUpdTime(new Date());
		findPwdRecord.setStatus(VerifyStatusEnum.CONFIRM.getCode());
		findPwdRecord.setConfirmTime(new Date());
		findPwdRecord.setUpdTime(findPwdRecord.getConfirmTime());
		if(!pm.isClosed()) pm.close();
		return AccountServiceEnum.OK.getCode();
	}

	@Override
	public UserAccount getUserAccount() {
    	log.warning("come in getUserAccount()");
    	UserLoginInfo userInfo = SessionHelper.getUserLoginInfo(getThreadLocalRequest());
    	if(userInfo==null || !userInfo.isLogined()){
    		return new UserAccount();
    	}
    	
    	UserAccount userAccount = null;
        PersistenceManager pm = PMF.get().getPersistenceManager();
        try{
            userAccount = pm.getObjectById(UserAccount.class,userInfo.getId());
        }catch(JDOObjectNotFoundException jdoonf){
        	pm.close();
        	return new UserAccount();
        }
        
        if(userAccount==null){
        	pm.close();
        	return new UserAccount();
        }    	
        //增加 头像位置
        if(userAccount.getFacePhotoId()>0){
        	MediaObject bObj = null;
        	try{
        		bObj = pm.getObjectById(MediaObject.class,userAccount.getFacePhotoId());
            	userAccount.setFacePhotoUrl("/displayPhoto.do?outputType=stream&blobKey="+bObj.getBlobKey());
        	}catch(JDOObjectNotFoundException jdoonf){        		
        	}
        }
        if(!pm.isClosed()) pm.close();
		return userAccount;
	}

	@Override
	public Integer updateUserAccount(UserAccount account) {
		// TODO Auto-generated method stub
		return null;
	}
	
	public Group findGroup(Long userId , int groupType ,String title ,PersistenceManager pm){
		Query q = pm.newQuery(Group.class);
		q.setFilter("userId == user_id && groupType == group_type && title == title_p");
		q.declareParameters("java.lang.Long user_id , Integer group_type , String title_p");
		q.setRange(0,1);
		Collection<Group> groups = (Collection<Group>) q.execute(userId,groupType,title);		
		if(groups!=null && groups.size()>0){
			return groups.iterator().next();
		}
		return null;
	}

	@Override
	public List<UserLoginInfo> getAllSessionUser() {
		//SessionHelper.updUserLoginInfo(getThreadLocalRequest());
		List<UserLoginInfo> allUser = new ArrayList<UserLoginInfo>();
		HashSet<String> allSession =  CacheHelper.getSessionAll();
		if(allSession!=null && !allSession.isEmpty()){
			Iterator<String> iter = allSession.iterator();
			while(iter.hasNext()){
				String sessionKey = iter.next();
				UserLoginInfo user = (UserLoginInfo)CacheHelper.get(sessionKey);
				if(user==null){
					//allSession.remove(sessionKey); 不能在 Iterator中删除元素
					//changed = true;
				}
				else{
					allUser.add(user);
				}
			}
			//if(changed){
			//	CacheHelper.updSessionAll(allSession);
			//}
		}
		log.warning("come in getAllSessionUser() return size="+allUser.size());
		return allUser;
	}
}
